//
// Copyright (c) 2013 Sobey Inc. All rights reserved.
//

__kernel void FillLinerGradient(	__global float *RValue,                  
                       				__global float *GValue,                  
                       				__global float *BValue,                  
									__global float *AValue,              
                       				const  int nTableSize,				
                       				const float fSinTheta,                 
                       				const float fCosTheta,                 
                       				const int nWidth,                      
                       				const int nHeight,                     
                       				__global unsigned char* Buffer)        
{																	
    const int row = get_global_id(0);								
    const int col = get_global_id(1);								
    float fPos = (row - nWidth / 2) * fCosTheta - (nHeight/2-col) * fSinTheta ; 
	int nPos = (int)(fPos + nTableSize / 2);									
    															
    const int nIndex = (col * nWidth + row)*4 ;					
    Buffer[nIndex ] =  RValue[nPos]*255;						
    Buffer[nIndex + 1] =  GValue[nPos]*255;						
    Buffer[nIndex + 2] =  BValue[nPos]*255;						
    Buffer[nIndex + 3] =  AValue[nPos]*255;						

}																			

__kernel void FillCenterGradient(	  __global float *RValue,                  
                       				  __global float *GValue,                  
                       				  __global float *BValue,                  
									  __global float *AValue,              
                       					const  int nTableSize,			
                       					const  int nCenterX,            
                       					const  int nCenterY,            
                       					const  int nWidth,              
                       					__global char* Buffer)                 
{																	
    const int row = get_global_id(0);								
    const int col = get_global_id(1);								
    int nDistance = (int)sqrt((float)((col-nCenterY)*(col-nCenterY) + (row-nCenterX)*(row-nCenterX)));
    																
    const int nIndex = (col * nWidth + row)*4 ;						
    Buffer[nIndex ] =  RValue[nDistance]*255;						
    Buffer[nIndex + 1] =  GValue[nDistance]*255;					
    Buffer[nIndex + 2] =  BValue[nDistance]*255;					
    Buffer[nIndex + 3] =  AValue[nDistance]*255;					
}																	


__kernel void FillCircleGradient(	__global float *RValue,                  
                       				__global float *GValue,                  
                       				__global float *BValue,                  
									__global float *AValue,              
                       				const  int nTableSize,				
                       				const  float fCenterX,                 
                       				const  float fCenterY,                 
                       				const  int nWidth,					
                       				const  int nHeight,					
                       				__global char* Buffer)                 
{																	
    const int row = get_global_id(0);								
    const int col = get_global_id(1);								
    float fLength1 = sqrt((float)((row+0.5f-fCenterX) * (row+0.5f-fCenterX) + (col+0.5-fCenterY)*(col+0.5-fCenterY)));
    float fDotRes = -(row+0.5f-fCenterX);								
    float fTheta = acos(fDotRes / fLength1);							
    if(col >= (float)(nHeight*0.5))										
		{  fTheta = (float)(2*3.1415926 - fTheta);}						
	 int nPos = (int)(fTheta* nTableSize / (2 * 3.1415926));			
    const int nIndex = (col * nWidth + row)*4 ;							
    Buffer[nIndex ] =  RValue[nPos]*255;								
    Buffer[nIndex + 1] =  GValue[nPos]*255;							
    Buffer[nIndex + 2] =  BValue[nPos]*255;							
    Buffer[nIndex + 3] =  AValue[nPos]*255;							
}																		


__kernel void FillQuadGradient(	  __global float *RValue,                   
                       		  __global float *GValue,                   
                       		  __global float *BValue,                   
								  __global float *AValue,               
								  __global float *pPtX,                 
								  __global float *pPtY,                 
                       			const  float fRadius,                  
                       			const  int nWidth,						
                       			__global char* Buffer)                  
{																		
    const int row = get_global_id(0);									
    const int col = get_global_id(1);									
	 const int nSize = 4;												
	 int i = 0;															
	 float fweight[4];													
	 float fsum = 0.0f;													
	 int distance[4];													
	 for(i=0;i<4;i++)													
	 {																	
		int dx = (int)(row - pPtX[i]);									
		int dy = (int)(col - pPtY[i]);									
		distance[i] = dx * dx + dy * dy;								
		distance[i] = (int)(sqrt((float)distance[i]) + 0.5f);				
	 }																		
	 for(i=0;i<4;i++)														
	 {	fweight[i] = (float)distance[i] / fRadius;							
		fweight[i] = pow(0.5f, fweight[i]);									
		fsum += fweight[i];													
		distance[i] = (int)(sqrt((float)distance[i]) + 0.5f);				
	 }																		
	 const int nIndex = (col * nWidth + row)*4 ;							
	 if(fsum < 0.0000001) fsum = 1.0f;										
	 float fRValue = 0.0f;													
	 float fGValue = 0.0f;													
	 float fBValue = 0.0f;													
	 float fAValue = 0.0f;													
	 for (int i=0; i<4; i++)												
	 { 																		
		fweight[i] = fweight[i] / fsum;										
		fRValue +=  RValue[i]*255*fweight[i];								
		fGValue +=  GValue[i]*255*fweight[i];								
		fBValue +=  BValue[i]*255*fweight[i];								
		fAValue +=  AValue[i]*255*fweight[i];								
	 }																	
    Buffer[nIndex ] =  fBValue;											
    Buffer[nIndex + 1] =  fGValue;										
    Buffer[nIndex + 2] =  fRValue;										
    Buffer[nIndex + 3] =  fAValue;										
}																		

typedef struct tag_TPColorValue											
{																		
	float	a;															
	float	r;															
	float	g;															
	float	b;															
} TPColorValue;

TPColorValue BufferConvert1(__global uchar* g_SrcBuffer,int nIndex, float fScale)			
{	
	TPColorValue Color;													
	Color.r = g_SrcBuffer[nIndex*4]   * fScale / 255.0f;
	Color.g = g_SrcBuffer[nIndex*4+1] * fScale / 255.0f;
	Color.b = g_SrcBuffer[nIndex*4+2] * fScale / 255.0f;
	Color.a = g_SrcBuffer[nIndex*4+3] * fScale / 255.0f;
	return Color;														
}
																		
__kernel void StretchBuffer(	const  int nImageWidth,					
							const  int nImageHeight,					
							const  int nWidth,							
							const  int nHeight,							
							__global uchar* g_SrcBuffer,			
							__global uchar* g_DstBuffer			
							)											
{																		
	const int row = get_global_id(0);									
	const int col = get_global_id(1);									
	float fSrcX = row * nImageWidth / (float)nWidth;					
	float fSrcY = col * nImageHeight/ (float)(nHeight);					
	int nSrcX = (int)(fSrcX);											
	int nSrcY = (int)(fSrcY);											
	float u = fSrcX - nSrcX;											
	float v = fSrcY - nSrcY;											
	TPColorValue Color[4];	

	Color[0] = BufferConvert1(g_SrcBuffer,nSrcY * nImageWidth + nSrcX,(1-u)*(1-v));			
	Color[1] = BufferConvert1(g_SrcBuffer,nSrcY * nImageWidth + nSrcX + 1, (1-u)*v);			
	if (1+nSrcY >= nImageHeight)																
	{																							
		Color[2] = BufferConvert1(g_SrcBuffer,(nSrcY) * nImageWidth + nSrcX,u*(1-v));			
		Color[3] = BufferConvert1(g_SrcBuffer,(nSrcY) * nImageWidth + nSrcX+1,u*v);				
	}																							
	else																						
	{																							
		Color[2] = BufferConvert1(g_SrcBuffer,(1+nSrcY) * nImageWidth + nSrcX,u*(1-v));			
		Color[3] = BufferConvert1(g_SrcBuffer,(1+nSrcY) * nImageWidth + nSrcX+1,u*v);			
	}																							
	TPColorValue NewColor ;	
	NewColor.a = 0.0f;
	NewColor.r = 0.0f;																	
	NewColor.g = 0.0f;																	
	NewColor.b = 0.0f;																	
																		
	int w=0;																					
	for (w=0;w<4;w++)																			
	{																							
		NewColor.a += Color[w].a;																
		NewColor.g += Color[w].g;																
		NewColor.b += Color[w].b;																
		NewColor.r += Color[w].r;																
	}																							
	if(NewColor.a > 1.0f) NewColor.a = 1.0f;													
	if(NewColor.r > 1.0f) NewColor.r = 1.0f;													
	if(NewColor.g > 1.0f) NewColor.g = 1.0f;													
	if(NewColor.b > 1.0f) NewColor.b = 1.0f;													
	int nIndex = (col * nWidth + row)*4 ;													
	g_DstBuffer[nIndex ] =  (unsigned char)(NewColor.r*255);												
	g_DstBuffer[nIndex + 1] = (unsigned char)( NewColor.g*255);											
	g_DstBuffer[nIndex + 2] = (unsigned char)( NewColor.b*255);											
	g_DstBuffer[nIndex + 3] = (unsigned char)( NewColor.a*255);											
}	